package ffte.test.types

import spinal.core._
import spinal.core.sim._
import ffte.types._

/**
 * FFTE类型系统核心测试套件
 * 精简版 - 保留最重要的测试用例
 */
object FFTE_TYPES_CORE_TEST {
  
  /**
   * 基础FixReal测试 - 最核心功能
   */
  class BasicFixRealTest extends Component {
    val io = new Bundle {
      val input = in SInt(16 bits)
      val output = out SInt(16 bits)
    }

    val testArea = new Area {
      val fixReal = FixReal(16, -8)
      fixReal.d.raw := io.input
      io.output := fixReal.d.raw
    }
  }

  /**
   * FixComplex核心测试
   */
  class CoreFixComplexTest extends Component {
    val io = new Bundle {
      val real_in = in SInt(16 bits)
      val imag_in = in SInt(16 bits)
      val real_out = out SInt(16 bits)
      val imag_out = out SInt(16 bits)
      val enable = in Bool()
    }

    val testArea = new Area {
      val complex1 = FixComplex(16, -8)
      val complex2 = FixComplex(16, -8)
      val result = FixComplex(16, -8)
      
      complex1.re.d.raw := io.real_in
      complex1.im.d.raw := io.imag_in
      complex2.re.d.raw := io.real_in
      complex2.im.d.raw := io.imag_in
      
      val sum = complex1 + complex2
      
      when(io.enable) {
        result.re.d.raw := sum.re.d.raw
        result.im.d.raw := sum.im.d.raw
      } otherwise {
        result.re.d.raw := complex1.re.d.raw
        result.im.d.raw := complex1.im.d.raw
      }
      
      io.real_out := result.re.d.raw
      io.imag_out := result.im.d.raw
    }
  }

  /**
   * VecComplex核心测试
   */
  class CoreVecComplexTest extends Component {
    val io = new Bundle {
      val real_in = in Vec(SInt(16 bits), 2)
      val imag_in = in Vec(SInt(16 bits), 2)
      val real_out = out Vec(SInt(16 bits), 2)
      val imag_out = out Vec(SInt(16 bits), 2)
    }

    val testArea = new Area {
      val vecComplex = VecComplex(2, 16, -8)
      val result = VecComplex(2, 16, -8)
      
      for (i <- 0 until 2) {
        vecComplex.d(i).re.d.raw := io.real_in(i)
        vecComplex.d(i).im.d.raw := io.imag_in(i)
        
        val doubled = vecComplex.d(i) + vecComplex.d(i)
        result.d(i).re.d.raw := doubled.re.d.raw
        result.d(i).im.d.raw := doubled.im.d.raw
        
        io.real_out(i) := result.d(i).re.d.raw
        io.imag_out(i) := result.d(i).im.d.raw
      }
    }
  }

  /**
   * 类型转换核心测试
   */
  class CoreTypeConversionTest extends Component {
    val io = new Bundle {
      val fixreal_input = in SInt(16 bits)
      val fixcomplex_real = out SInt(16 bits)
      val fixcomplex_imag = out SInt(16 bits)
    }

    val conversionArea = new Area {
      val fixReal = FixReal(16, -8)
      fixReal.d.raw := io.fixreal_input
      
      val fixComplex = FixComplex(16, -8)
      fixComplex.re.d.raw := fixReal.d.raw
      fixComplex.im.d.raw := S(0)
      
      io.fixcomplex_real := fixComplex.re.d.raw
      io.fixcomplex_imag := fixComplex.im.d.raw
    }
  }

  /**
   * 运行核心测试
   */
  def main(args: Array[String]): Unit = {
    println("🚀 开始FFTE类型系统核心测试...")
    
    // 测试1：基础FixReal
    println("\n1️⃣ 测试基础FixReal...")
    SimConfig.withWave.compile(new BasicFixRealTest()).doSim { dut =>
      dut.clockDomain.forkStimulus(period = 10)
      
      // 测试基本功能
      dut.io.input #= Math.round(0.5 * 128)
      dut.clockDomain.waitSampling(1)
      
      val result = dut.io.output.toInt
      println(f"FixReal直通: 输入${dut.io.input.toInt} -> 输出$result")
      assert(result == Math.round(0.5 * 128), "FixReal基础功能验证失败")
    }
    
    // 测试2：FixComplex核心功能
    println("\n2️⃣ 测试FixComplex核心功能...")
    SimConfig.withWave.compile(new CoreFixComplexTest()).doSim { dut =>
      dut.clockDomain.forkStimulus(period = 10)
      
      // 测试复数加法 (1+2i) + (1+2i) = (2+4i)
      dut.io.enable #= true
      dut.io.real_in #= Math.round(1.0 * 128)
      dut.io.imag_in #= Math.round(2.0 * 128)
      dut.clockDomain.waitSampling(1)
      
      val real_out = dut.io.real_out.toInt
      val imag_out = dut.io.imag_out.toInt
      println(f"FixComplex加法: (${real_out}/128 + ${imag_out}/128i)")
      assert(real_out == Math.round(2.0 * 128), "实部验证失败")
      assert(imag_out == Math.round(4.0 * 128), "虚部验证失败")
    }
    
    // 测试3：VecComplex核心功能
    println("\n3️⃣ 测试VecComplex核心功能...")
    SimConfig.withWave.compile(new CoreVecComplexTest()).doSim { dut =>
      dut.clockDomain.forkStimulus(period = 10)
      
      // 测试向量元素乘以2
      dut.io.real_in(0) #= Math.round(1.0 * 128)
      dut.io.imag_in(0) #= Math.round(2.0 * 128)
      dut.io.real_in(1) #= Math.round(3.0 * 128)
      dut.io.imag_in(1) #= Math.round(4.0 * 128)
      dut.clockDomain.waitSampling(1)
      
      val real0 = dut.io.real_out(0).toInt
      val imag0 = dut.io.imag_out(0).toInt
      val real1 = dut.io.real_out(1).toInt
      val imag1 = dut.io.imag_out(1).toInt
      
      println(f"VecComplex[0]: (${real0}/128 + ${imag0}/128i)")
      println(f"VecComplex[1]: (${real1}/128 + ${imag1}/128i)")
      
      assert(real0 == Math.round(2.0 * 128), "VecComplex[0]实部验证失败")
      assert(imag0 == Math.round(4.0 * 128), "VecComplex[0]虚部验证失败")
      assert(real1 == Math.round(6.0 * 128), "VecComplex[1]实部验证失败")
      assert(imag1 == Math.round(8.0 * 128), "VecComplex[1]虚部验证失败")
    }
    
    // 测试4：类型转换
    println("\n4️⃣ 测试类型转换...")
    SimConfig.withWave.compile(new CoreTypeConversionTest()).doSim { dut =>
      dut.clockDomain.forkStimulus(period = 10)
      
      // 测试FixReal到FixComplex转换
      dut.io.fixreal_input #= Math.round(2.5 * 128)
      dut.clockDomain.waitSampling(1)
      
      val real_out = dut.io.fixcomplex_real.toInt
      val imag_out = dut.io.fixcomplex_imag.toInt
      
      println(f"FixReal→FixComplex: ${dut.io.fixreal_input.toInt}/128 → ($real_out/128 + ${imag_out}/128i)")
      assert(real_out == Math.round(2.5 * 128), "类型转换实部验证失败")
      assert(imag_out == 0, "类型转换虚部应为0")
    }
    
    println("\n🎉 所有核心测试通过！FFTE类型系统验证成功。")
    println("\n📋 核心功能验证完成:")
    println("  ✅ FixReal定点数运算")
    println("  ✅ FixComplex复数运算")  
    println("  ✅ VecComplex向量运算")
    println("  ✅ 类型转换功能")
  }
}